package xyz.xtt.exchange.service.impl;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.google.common.primitives.Ints;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import xyz.xtt.exchange.constants.AssetTypeEnum;
import xyz.xtt.exchange.entity.TblAsset;
import xyz.xtt.exchange.entity.TblAssetExt;
import xyz.xtt.exchange.entity.TblAssetStaticResource;
import xyz.xtt.exchange.entity.TblAssetTransaction;
import xyz.xtt.exchange.entity.TblUser;
import xyz.xtt.exchange.mapper.TblAssetMapper;
import xyz.xtt.exchange.service.ITblAssetService;
import xyz.xtt.exchange.vo.AssetDetailsVo;
import xyz.xtt.exchange.vo.AssetTradeRecordVo;
import xyz.xtt.exchange.vo.AssetVo;

/**
 * <p>
 * 资产基础信息表 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-10-23
 */

@Service
public class TblAssetServiceImpl extends ServiceImpl<TblAssetMapper, TblAsset> implements ITblAssetService {
	@Autowired
	TblAssetMapper assetMapper;

	/**
	 * 获取个人资产
	 */
	public List<TblAsset> getMyAssets(String uid, Integer state, String firstType, String secondType) {
		QueryWrapper<TblAsset> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("owner_id", uid).eq(!firstType.isEmpty(), "firstType", firstType);
		queryWrapper.eq(!secondType.isEmpty(), "second_type", secondType);
		queryWrapper.eq(state != null, "show_state", state);
		return assetMapper.selectList(queryWrapper);
	}

	/**
	 * 获取资产详情
	 */
	public AssetDetailsVo getAssetDetails(String goodsId, String firstType, String secondType) {
		AssetDetailsVo assetDetails = assetMapper.getAssetDetailsById(goodsId, firstType, secondType);
		if (assetDetails == null)
			return null;
		switch (firstType) {
		case "0":
			return getGroundInfo(assetDetails);
		case "1":
			return getCertificate(assetDetails);
		default:
			return null;
		}
	}

	/**
	 * 地皮资产详情
	 *
	 * @param assetDetails
	 * @return
	 */
	public AssetDetailsVo getGroundInfo(AssetDetailsVo assetDetails) {
		if (assetDetails != null) {
			JSONObject entries = JSONUtil.parseObj(assetDetails.getMetaData());
			assetDetails.setArea(entries.getStr("area"));
			assetDetails.setClassifyName(AssetTypeEnum.queryConvert(Ints.tryParse(assetDetails.getFirstType())).desc());
			JSONArray first = JSONUtil.parseArray(entries.getStr("first"));
			JSONArray second = JSONUtil.parseArray(entries.getStr("second"));
			assetDetails.setFirstCertificateAmount(first.size());
			assetDetails.setSecondCertificateAmount(second.size());
		}
		// 地皮交易记录
		List<AssetTradeRecordVo> tradeByIdForList = assetMapper.getTradeRecordById(assetDetails.getGoodsId());

		// 地皮下的经营证（这里的参数是资产表主键）
		QueryWrapper<TblAsset> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("parent_id", assetDetails.getId());
		List<TblAsset> certificates = assetMapper.selectList(queryWrapper);

		assetDetails.setCertificateList(certificates);
		assetDetails.setGroundtradeRecordVoList(tradeByIdForList);
		return assetDetails;
	}

	public AssetDetailsVo getCertificate(AssetDetailsVo assetDetails) {
		if (assetDetails != null) {
			// 填充经营证关联地皮信息
			QueryWrapper<TblAsset> queryWrapper = new QueryWrapper<>();
			queryWrapper.eq("id", assetDetails.getParentId());
			TblAsset tblAsset = assetMapper.selectOne(queryWrapper);
			assetDetails.setGroundInfo(tblAsset);
			// 填充地皮下的经营证信息
			JSONObject entries = JSONUtil.parseObj(tblAsset.getMetaData());
			JSONArray first = JSONUtil.parseArray(entries.getStr("first"));
			JSONArray second = JSONUtil.parseArray(entries.getStr("second"));
			assetDetails.setFirstCertificateAmount(first.size());
			assetDetails.setSecondCertificateAmount(second.size());
		}
		return assetDetails;
	}

	@Override
	public TblAsset orderQueryAsset(Long assetId) {
		LambdaQueryChainWrapper<TblAsset> query = new LambdaQueryChainWrapper<>(baseMapper);
		return query.eq(TblAsset::getId, assetId).one();
	}

	@Override
	public AssetVo queryAssetVo(Long assetId) {
//		MPJLambdaWrapper<TblAsset> query = JoinWrappers
//				.lambda(TblAsset.class)
//				.select(TblAsset::getAssetNo, TblAsset::getAssetName)
//				.selectAs(TblAssetExt::getSellStartDatetime, AssetVo::getSellStartDatetime)
//				.leftJoin(TblAssetExt.class, TblAssetExt::getAssetId, TblAsset::getId)
//				.selectAs(TblAssetStaticResource::getLogoUri, AssetVo::getLogoUri)
//				.selectAs(TblAssetStaticResource::getDisplayUri, AssetVo::getDisplayUri)
//				.selectAs(TblAssetStaticResource::getFileUri, AssetVo::getFileUri)
//				.leftJoin(TblAssetStaticResource.class, TblAssetStaticResource::getAssetId, TblAsset::getId)
//				.eq(TblAsset::getId, assetId);
		MPJLambdaWrapper<TblAsset> query = JoinWrappers
				.lambda(TblAsset.class)
				.select(TblAsset::getAssetNo, TblAsset::getAssetName)
				.select(TblAssetExt::getSellStartDatetime)
				.leftJoin(TblAssetExt.class, TblAssetExt::getAssetId, TblAsset::getId)
				.select(TblAssetStaticResource::getLogoUri, TblAssetStaticResource::getDisplayUri, TblAssetStaticResource::getFileUri)
				.leftJoin(TblAssetStaticResource.class, TblAssetStaticResource::getAssetId, TblAsset::getId)
				.eq(TblAsset::getId, assetId);
		return query.one(AssetVo.class);
	}

	@Override
	public List<AssetVo> queryAssetVoPage(String uid) {
		MPJLambdaWrapper<TblAsset> query = JoinWrappers
				.lambda(TblAsset.class)
				.select(TblAsset::getAssetNo, TblAsset::getAssetName)
				.select(TblAssetExt::getSellStartDatetime)
				.leftJoin(TblAssetExt.class, TblAssetExt::getAssetId, TblAsset::getId)
				.select(TblAssetStaticResource::getLogoUri, TblAssetStaticResource::getDisplayUri, TblAssetStaticResource::getFileUri)
				.leftJoin(TblAssetStaticResource.class, TblAssetStaticResource::getAssetId, TblAsset::getId)
				.eq(TblAsset::getOwnerId, uid);
		Page<AssetVo> page = query.page(new Page<AssetVo>(0, 10), AssetVo.class);
		return page.getRecords();
	}

	@Override
	public List<AssetVo> subqueryAssetVoPage(String uid) {
		MPJLambdaWrapper<TblAsset> leftJoin = JoinWrappers.lambda(TblAsset.class)
//				.selectSub(TblAsset.class, w -> w.select(TblAsset::getAssetNo, TblAsset::getAssetName).eq(TblAsset::getOwnerId, uid));
//				.selectSub(TblAsset.class, x->x.eq(TblAsset::getOwnerId, uid), TblAsset.class)
				.selectSub(TblAsset.class, x -> x.eq(TblAsset::getOwnerId, uid), TblAsset::getId)
				.leftJoin(TblAssetExt.class, TblAssetExt::getAssetId, TblAsset::getId)
				.select(TblAssetStaticResource::getLogoUri, TblAssetStaticResource::getDisplayUri, TblAssetStaticResource::getFileUri)
				.leftJoin(TblAssetStaticResource.class, TblAssetStaticResource::getAssetId, TblAsset::getId);
		return leftJoin.list(AssetVo.class);
	}

	@Override
	public List<AssetVo> fromqueryAssetVoPage(String uid, Integer curPage) {
		LambdaUpdateChainWrapper<TblAsset> update = new LambdaUpdateChainWrapper<>(assetMapper);
		update.in(TblAsset::getId, new LambdaQueryWrapper<TblAsset>().select(TblAsset::getId).last("limit 10"));
		update.set(TblAsset::getFirstType, 1);
		update.update();

		int pageSize = 10;
		curPage = Optional.ofNullable(curPage).orElse(0);
		String last = String.format("limit %d, %d", curPage * pageSize, pageSize);
		MPJLambdaWrapper<TblAsset> leftJoin = JoinWrappers
				.lambda(TblAsset.class)
				.select(TblAsset::getAssetNo, TblAsset::getAssetName, TblAsset::getId)
				.from(x -> x.selectAll().eq(TblAsset::getOwnerId, uid).last(last))
				.select(TblAssetExt::getSellStartDatetime)
				.leftJoin(TblAssetExt.class, TblAssetExt::getAssetId, TblAsset::getId)
				.select(TblAssetStaticResource::getLogoUri, TblAssetStaticResource::getDisplayUri, TblAssetStaticResource::getFileUri)
				.leftJoin(TblAssetStaticResource.class, TblAssetStaticResource::getAssetId, TblAsset::getId);
		return leftJoin.list(AssetVo.class);
	}

	/*
	 * 关联一个表两次
	 * 
	 * (non-Javadoc)
	 * 
	 * @see
	 * xyz.xtt.exchange.service.ITblAssetService#queryAssetTradeRecord(java.lang.
	 * String)
	 */
	@Override
	public List<AssetTradeRecordVo> queryAssetTradeRecord(String goodsId) {
		MPJLambdaWrapper<TblAssetTransaction> query = JoinWrappers
				.lambda(TblAssetTransaction.class)
				.selectAll()
				.from(x -> x.selectAll().eq(TblAsset::getGoodsId, goodsId))
				.selectAs("buy", TblUser::getNickname, AssetTradeRecordVo::getBuyerNickname)
				.selectAs("buy", TblUser::getAvatarUri, AssetTradeRecordVo::getBuyerAvatarUri)
				.selectAs("sell", TblUser::getNickname, AssetTradeRecordVo::getSellerNickname)
				.selectAs("sell", TblUser::getAvatarUri, AssetTradeRecordVo::getSellerAvatarUri)
				.selectAs(TblAssetTransaction::getSellPattern, AssetTradeRecordVo::getTradePattern)
				.selectAs(TblAssetTransaction::getDealCreateDatetime, AssetTradeRecordVo::getTradeTime)
				.leftJoin(TblUser.class, "buy", TblUser::getAppUserId, TblAssetTransaction::getBuyerUserId)
				.leftJoin(TblUser.class, "sell", TblUser::getAppUserId, TblAssetTransaction::getSellerUserId);
		return query.list(AssetTradeRecordVo.class);
	}

	@Override
	public AssetDetailsVo queryDetail(String goodsId) {
		MPJLambdaWrapper<TblAsset> query = JoinWrappers
				.lambda(TblAsset.class)
				.selectAll()
				.selectAs(TblAssetExt::getSellStartDatetime, AssetDetailsVo::getSellStartTime)
				.selectAs(TblAssetExt::getSellEndDatetime, AssetDetailsVo::getSellEndTime)
				.selectAs(TblAssetExt::getReferProtocol, AssetDetailsVo::getProtocol)
				.selectAs(TblAssetExt::getChainTxHash, AssetDetailsVo::getHash)
				.select(TblAssetExt::getChainName, TblAssetExt::getTokenId)
				.leftJoin(TblAssetExt.class, TblAssetExt::getAssetId, TblAsset::getId)
				.eq(TblAsset::getGoodsId, goodsId);
		AssetDetailsVo one = query.one(AssetDetailsVo.class);
		if (Objects.isNull(one)) {
			return null;
		}
		List<AssetTradeRecordVo> queryAssetTradeRecord = queryAssetTradeRecord(goodsId);
		if (Objects.equals(one.getFirstType(), String.valueOf(AssetTypeEnum.LAND.code()))) {
			List<TblAsset> certificateList = JoinWrappers.lambda(TblAsset.class).eq(TblAsset::getParentId, goodsId).list();
			one.setCertificateList(certificateList);
			one.setCertificateTradeRecordVoList(queryAssetTradeRecord);
		} else if (Objects.equals(one.getFirstType(), String.valueOf(AssetTypeEnum.BIZ_CERTIFICATE.code()))) {
			TblAsset land = JoinWrappers.lambda(TblAsset.class).eq(TblAsset::getGoodsId, goodsId).one();
			one.setGroundInfo(land);
			one.setGroundtradeRecordVoList(queryAssetTradeRecord);
		}
		return one;
	}

	public void queryDetailEx(String goodsId) {
		MPJLambdaWrapper<TblAsset> query = JoinWrappers
				.lambda(TblAsset.class)
				.in(TblAsset::getAssetNo, TblAssetExt.class, in -> in.select(TblAsset::getId).eq(TblAsset::getDescription, "xx"));
		List<AssetDetailsVo> list = query.list(AssetDetailsVo.class);
	}

	@Override
	public List<String> queryBuyerChainAccount(String goodsId) {
		MPJLambdaWrapper<TblAssetTransaction> query = JoinWrappers
				.lambda(TblAssetTransaction.class)
				.select(TblAssetTransaction::getBuyerChainAccount)
				.eq(TblAssetTransaction::getGoodsId, goodsId);
		Page<String> page = query.page(new Page<String>(1, 10), String.class);
		return page.getRecords();
	}

	public List<Map<String, Object>> listx() {
		List<Map<String, Object>> selectList = SqlRunner.db(TblAssetTransaction.class).selectList("", null);
		return selectList;
	}
}
